(function ($) {
    // ---------------------------------------面向对象方式实现搜索功能-------------------------------------------------------------
    /**
     * Search功能说明:
     * 1) cache:  缓存数据,提供  添加/删除/查询 功能
     *
     * 2) Search:
     * 默认参数: DEFAULTS ={autocomplete: false,url: 'xx',getDataInterval: 200}
     * 实例化触发:
     *   (1) 代理子元素'搜索按钮' click事件;触发表单提交
     *   (2) 如果开启了自动完成( options.autocomplete = true ) 执行: autocomplete()
     * 包含的功能:
     *   (1) submit()   提交表单
     *   (2) autocomplete()  对表单输入框(input元素),绑定事件
     *          2-1绑定 input 事件,调用 getData()
     *          2-2绑定 focus 事件,调用 showLayer()
     *          2-3绑定 click 事件,执行: return false;
     *   (3) getData() 根据输入框value,触发 search-noData() or search-getData() or ajax请求
     *   (4) showLayer()   显示下拉框
     *   (5) hideLayer()   隐藏下拉框
     *   (6) getInputVal()  获取表单input输入框的value
     *   (6) setInputVal()  设置表单input输入框的value
     *   (7) appendLayer(html)  把html拼接到下拉框,并将 loaded 设为 true
     *
     *
     */
    'use strict';//严格模式
    let cache = {
        data: {},
        count: 0,
        addData: function (key, data) {
            if (!this.data[key]) {
                this.data[key] = data;
                this.count++;
            }
        },
        readData: function (key) {
            return this.data[key];
        },
        deleteDataByKey: function (key) {
            delete this.data[key];
            this.count--;
        },
        deleteDataByOrder: function (num) {
            let count = 0;
            for (let p in this.data) {
                if (count >= num) break;
                count++;
                this.deleteDataByKey(p);
            }
        }
    };

    function Search($elem, options) {
        this.$elem = $elem;//当前的search框
        this.options = options;
        this.$form = this.$elem.find('.search-form');//表单
        this.$input = this.$elem.find('.search-input-box');//表单输入框
        this.$layer = this.$elem.find('.search-layer');//下拉列表
        this.loaded = false;//数据加载标识
        this.$elem.on('click', '.search-btn', $.proxy(this.submit, this));//代理按钮的点击事件,更新上下文
        if (this.options.autocomplete) this.autocomplete();//开启自动填写
    }

    Search.prototype.submit = function () {
        if (this.getInputVal() === '') return false;
        this.$form.submit();
    };
    Search.prototype.autocomplete = function () {
        let self = this;
        this.$input.on('input', function () { //监听表单input框内容变化
            if (self.options.getDataInterval) {
                clearTimeout(self.timer);
                self.timer = setTimeout(function () {
                    self.getData();
                }, self.options.getDataInterval);
            } else self.getData();
        }).on('focus', $.proxy(this.showLayer, this)).on('click', function () {
            return false;
        });
        this.$layer.showHide(this.options);//绑定showHide功能
        $(document).on('click', $.proxy(this.hideLayer, this));
    };
    Search.prototype.getData = function () {
        let self = this;
        let inputVal = this.getInputVal();
        if (inputVal === '') return self.$elem.trigger('search-noData');
        if (cache.readData(inputVal)) return self.$elem.trigger('search-getData', [cache.readData(inputVal)]);//从缓存里拿数据
        if (this.jqXHR) this.jqXHR.abort();//如果正在执行ajax,则取消本次执行
        // 执行ajax
        this.jqXHR = $.ajax({
            url: this.options.url + inputVal,
            dataType: 'jsonp'
        }).done(function (data) {
            cache.addData(inputVal, data);
            self.$elem.trigger('search-getData', [data]);
        }).fail(function () {
            self.$elem.trigger('search-noData');
        }).always(function () {
            self.jqXHR = null;
        });

    };
    Search.prototype.showLayer = function () {
        if (!this.loaded) return; //下来框没有子元素,无需显示
        this.$layer.showHide('show');
    };
    Search.prototype.hideLayer = function () {
        this.$layer.showHide('hide');
    };
    Search.prototype.getInputVal = function () {
        return $.trim(this.$input.val());
    };
    Search.prototype.setInputVal = function (val) {
        this.$input.val(removeHtmlTags(val));
        //使用正则表达式,移除字符串里的标签
        function removeHtmlTags(str) {
            return str.replace(/<(?:[^>'"]|"[^"]*"|'[^']*')*>/g, '');
        }
    };
    Search.prototype.appendLayer = function (html) {
        this.$layer.html(html);
        this.loaded = !!html;//转化为boolean值
    };
    Search.DEFAULTS = {
        autocomplete: false,
        url: 'https://suggest.taobao.com/sug?code=utf-8&_ksTS=1484204931352_18291&callback=jsonp18292&k=1&area=c2c&bucketid=6&q=',
        getDataInterval: 200
    };

    /**
     * option参数:  {autocomplete: true, css3: false, js: false, animation: 'fade', getDataInterval: 0}
     *         autocomplete = false  -->点击搜索按钮,触发表单提交
     *         autocomplete = true   -->点击搜索按钮,触发表单提交  + 表单input框的 input 事件  + 表单input框的 focus 事件 + 表单input框的 click 事件
     *
     */
    $.fn.extend({
        search: function (option, value) {
            return this.each(function () {
                let $this = $(this),//每一个Search框
                    search = $this.data('search'),
                    options = $.extend({}, Search.DEFAULTS, $(this).data(), typeof option === 'object' && option);
                if (!search) $this.data('search', search = new Search($this, options));//单例
                if (typeof search[option] === 'function') search[option](value);//执行函数
            });
        }
    });
    // ---------------------------------------面向对象方式实现搜索功能--end-----------------------------------------------------------

    // ---------------------------------------search调用--start-----------------------------------------------------------

    //header search
    let $headerSearch = $('#header-search');
    let html = '',
        maxNum = 10;
    //加载下拉框的子元素
    $headerSearch
        .on('search-getData', function (e, data) {
            let $this = $(this);
            html = createHeaderSearchLayer(data, maxNum);
            $this.search('appendLayer', html);
            // 将生成的html呈现在页面中
            if (html) $this.search('showLayer');
            else $this.search('hideLayer');
        })
        .on('search-noData', function (e) {
            $(this).search('hideLayer').search('appendLayer', '');// 没获得数据处理
        })
        .on('click', '.search-layer-item', function () {
            // 点击每项时，提交
            $headerSearch.search('setInputVal', $(this).html());
            $headerSearch.search('submit');
        });

    $headerSearch.search({autocomplete: true, getDataInterval: 20});//初始化Search

    // 获取数据,生成html
    function createHeaderSearchLayer(data, maxNum) {
        let html = '',
            dataNum = data['result'].length;
        if (dataNum === 0) return '';
        for (let i = 0; i < dataNum; i++) {
            if (i >= maxNum) break;
            html += '<li class="search-layer-item text-ellipsis">' + data['result'][i][0] + '</li>';
        }
        return html;
    }
    // ---------------------------------------search调用--end-----------------------------------------------------------

})(jQuery);